package com.hengxinguotong.zhihuichengjian.utils;

import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * 生成错误信息日志文件
 * Created by ding on 2015/10/29.
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler
{

	//系统默认的UncaughtException处理类
	private Thread.UncaughtExceptionHandler mDefaultHandler;
	//CrashHandler实例
	private static CrashHandler INSTANCE = new CrashHandler();
	//程序的Context对象
	private Context mContext;
	//用来存储设备信息和异常信息
	private Map<String, String> infos = new HashMap<String, String>();
	//版本名称
	private String versionName = "";
	//版本号
	private String versionCode ="";
	//手机型号
	private String MODEL ="";
	//SDK版本
	private String SDK ="";
	//系统版本
	private String RELEASE ="";

	/** 保证只有一个CrashHandler实例 */
	private CrashHandler()
	{
	}

	/** 获取CrashHandler实例 ,单例模式 */
	public static CrashHandler getInstance()
	{
		return INSTANCE;
	}

	/**
	 * 初始化
	 *
	 * @param context
	 */
	public void init(Context context)
	{
		mContext = context;
		//获取系统默认的UncaughtException处理器
		mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
		//设置该CrashHandler为程序的默认处理器
		Thread.setDefaultUncaughtExceptionHandler(this);
	}

	/**
	 * 当UncaughtException发生时会转入该函数来处理
	 */
	@Override
	public void uncaughtException(Thread thread, Throwable ex)
	{
		if (!handleException(ex) && mDefaultHandler != null)
		{
			//如果用户没有处理则让系统默认的异常处理器来处理
			mDefaultHandler.uncaughtException(thread, ex);
		}
		else
		{
			try
			{
				Thread.sleep(3000);
			}
			catch (InterruptedException e)
			{
				LogUtil.w("error : "+ e);
			}

			mDefaultHandler.uncaughtException(thread, ex);

			//退出程序
			//            android.os.Process.killProcess(android.os.Process.myPid());
			//            System.exit(1);
		}
	}

	/**
	 * 自定义错误处理,收集错误信息 发送错误报告等操作均在此完成.
	 *
	 * @param ex
	 * @return true:如果处理了该异常信息;否则返回false.
	 */
	private boolean handleException(Throwable ex)
	{
		LogUtil.w("。。。。。。。。。。。。。。。。。。。。。。。。进来了 handleException(Throwable ex)");
		if (ex == null)
		{
			return false;
		}
		//使用Toast来显示异常信息
		new Thread()
		{
			@Override
			public void run()
			{
				Looper.prepare();
				//                Toast.makeText(mContext, "很抱歉,程序出现异常,即将退出.", Toast.LENGTH_LONG).show();
				Looper.loop();
			}
		}.start();
		//收集设备参数信息
		collectDeviceInfo(mContext);
		//保存日志文件
		LogUtil.w("ex:" + ex.toString() + "--" + ex.getLocalizedMessage());
		saveCrashInfo2File(ex);
		return true;
	}

	/**
	 * 收集设备参数信息
	 * @param ctx
	 */
	@SuppressWarnings("deprecation")
	public void collectDeviceInfo(Context ctx)
	{
		try
		{
			PackageManager pm = ctx.getPackageManager();
			PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
			if (pi != null)
			{
				versionName = pi.versionName == null ? "null" : pi.versionName;
				versionCode = pi.versionCode + "";
				infos.put("versionName", versionName);
				infos.put("versionCode", versionCode);
				//版本名称
				versionName = "版本名称："+versionName+"\n";
				//版本号
				versionCode = "版本号："+versionCode+"\n";
				//手机型号
				MODEL = "手机型号："+ Build.MODEL+"\n";
				//SDK版本
				SDK = "SDK版本："+ Build.VERSION.SDK+"\n";
				//系统版本
				RELEASE = "系统版本："+ Build.VERSION.RELEASE+"\n";
			}
		}
		catch (PackageManager.NameNotFoundException e)
		{
			LogUtil.w("an error occured when collect package info"+ e);
		}
		Field[] fields = Build.class.getDeclaredFields();
		for (Field field : fields)
		{
			try
			{
				field.setAccessible(true);
			}
			catch (Exception e)
			{
				LogUtil.w("an error occured when collect crash info" + e);
			}
		}
	}

	/**
	 * 保存错误信息到文件中
	 *
	 * @param ex
	 * @return    返回文件名称,便于将文件传送到服务器
	 */
	private String saveCrashInfo2File(Throwable ex)
	{

		LogUtil.w("。。。。。。。。。。。。。。。。。。。。。。。。进来了 saveCrashInfo2File(Throwable ex)");
		//组装异常内容
		String curTime =  new TimeUtils().getCurrentTime() + "日志输出：\n";//当前时间----yyyy-MM-dd HH:mm:ss
		//版本名称 versionName
		//版本号 versionCode
		//手机型号 MODEL
		//SDK版本
		//系统版本 RELEASE
		curTime=curTime+MODEL+SDK+RELEASE+versionName+versionCode;
		StringBuffer sb = new StringBuffer();
		sb.append(curTime);

		Writer writer = new StringWriter();
		PrintWriter printWriter = new PrintWriter(writer);
		ex.printStackTrace(printWriter);
		Throwable cause = ex.getCause();
		while (cause != null)
		{
			cause.printStackTrace(printWriter);
			cause = cause.getCause();
		}
		printWriter.close();
		String result = writer.toString();
		sb.append(result);
		try{
			String fileName = TimeUtils.getDetailsDate()+"exceptionLog.txt";//"yyyy-MM-dd"
			String filePath = Environment.getExternalStorageDirectory()+"/escst/";
			String fileContent=sb.toString();
			FileUtils.writeTxtToFile(fileContent, filePath, fileName);
//			File file=new File(Environment.getExternalStorageDirectory()+"/estar/", TimeUtils.getDetailsDate()+ "exceptionLog.txt");
//
//			if(!file.exists()){
//				file.createNewFile();
//			}
//			String path =file.getAbsolutePath();
//			FileOutputStream fos = new FileOutputStream(path);
//			fos.write(sb.toString().getBytes());
//			fos.close();

			try {
				//退出程序
				android.os.Process.killProcess(android.os.Process.myPid());//获取PID
				System.exit(0); //常规java、c#的标准退出法，返回值为0代表正常退出
				android.os.Process.killProcess(android.os.Process.myPid());
				System.exit(1);
				Runtime.getRuntime().exit(0);
			} catch (Exception e) {
				Runtime.getRuntime().exit(-1);
			}
			return fileName;
		}
		catch (Exception e)
		{
			Runtime.getRuntime().exit(-1);
			LogUtil.w("an error occured while writing file.." + e);
			LogUtil.w("。。。。。。。。。。。。。。。。。。。。。。。。输入报错 saveCrashInfo2File(Throwable ex)");
		}
		return null;
	}


}